#' @param row.names When \code{counts} is a \code{data.frame} or
#' \code{data.frame}-derived object: an optional vector of feature names to be
#' used
#'
#' @rdname CreateSeuratObject
#' @method CreateSeuratObject default
#' @export
#'
CreateSeuratObject.default <- function(
  counts,
  project = 'SeuratProject',
  assay = 'RNA',
  names.field = 1,
  names.delim = '_',
  meta.data = NULL,
  min.cells = 0,
  min.features = 0,
  row.names = NULL,
  ...
) {

  # 如果 meta.data 参数非空
  if (!is.null(x = meta.data)) {
    # 进一步检查：如果 meta.data 行名(cid) 不全在 counts的列名(cid) 中
    if (!all(rownames(x = meta.data) %in% colnames(x = counts))) {
      warning("Some cells in meta.data not present in provided counts matrix")
    }
  }

  # 创建Assay对象
  assay.data <- CreateAssayObject(
    counts = counts,
    min.cells = min.cells,
    min.features = min.features,
    row.names = row.names
  )

  # 如果 meta.data 参数非空 //这个可以和第一个if合并，那里只有一个warning。
  if (!is.null(x = meta.data)) {
    # 求共有 cid: meta.data 与 counts矩阵
    common.cells <- intersect(
      x = rownames(x = meta.data), y = colnames(x = assay.data)
    )
    meta.data <- meta.data[common.cells, , drop = FALSE] #这个参数 drop=F 见tips1
  }

  # 更新 key，看懂函数了，但不懂干啥用的 //todo tips2 说了一些我的理解
  Key(object = assay.data) <- suppressWarnings(expr = 
    UpdateKey(key = tolower( x = assay )) 
    #输入参数assay默认值是 "RNA"，取小写后是 "rna"
    # 由 UpdateKey() 添加下划线后缀后，默认是 Key(sce) #"rna_"
  )
  
  # 返回值又调用了 CreateSeuratObject.Assay, 因为第一个参数是 Assay 类的对象
  return(CreateSeuratObject(
    counts = assay.data,
    project = project,
    assay = assay,
    names.field = names.field,
    names.delim = names.delim,
    meta.data = meta.data,
    ...
  ))
}


#' @rdname CreateSeuratObject
#' @method CreateSeuratObject Assay
#' @export
#'
CreateSeuratObject.Assay <- function(
  counts,
  project = 'SeuratProject',
  assay = 'RNA',
  names.field = 1,
  names.delim = '_',
  meta.data = NULL,
  ...
) {

  # 如果 meta.data 非空
  if (!is.null(x = meta.data)) {
    # 如果 meta.data 行名(cell id)为空，则报错退出
    if (is.null(x = rownames(x = meta.data))) {
      stop("Row names not set in metadata. Please ensure that rownames of metadata match column names of data matrix")
    }
    
    # 如果meta.data的cid比counts的cid多，则警告，并取cid交集，并对 meta.data取子集
    if (length(x = setdiff(x = rownames(x = meta.data), y = colnames(x = counts)))) {
      warning("Some cells in meta.data not present in provided counts matrix.")
      meta.data <- meta.data[intersect(x = rownames(x = meta.data), y = colnames(x = counts)), , drop = FALSE] #drop=F 即便只有一列，也不丢掉列名
    }

    # 如果 meta.data 是df (解析2 有例子)
    if (is.data.frame(x = meta.data)) {
      # 新建数据框，空白，行名为counts的列名(cid)
      new.meta.data <- data.frame(row.names = colnames(x = counts))

      #对于 meta.data 的每一列循环
      for (ii in 1:ncol(x = meta.data)) {
        # 按 meta.data 的cid，保持列名，赋值给 新meta.data
        # 对于 meta.data没有 而counts 特有的cid，则数据框内使用NA填充
        new.meta.data[rownames(x = meta.data), colnames(x = meta.data)[ii]] <- meta.data[, ii, drop = FALSE]
      }
      meta.data <- new.meta.data
    }
  }


  # Check assay key
  # 对于Assay的key，长度是0的，或者 非字符串的，更新key
  if (!length(x = Key(object = counts)) || !nchar(x = Key(object = counts))) {
    Key(object = counts) <- UpdateKey(key = tolower(x = assay))
  }

  # 把Assay对象放入list，并用输入参数 assay="RNA" 命名
  assay.list <- list(counts)
  names(x = assay.list) <- assay

  # Set idents
  # counts列名中 _ 的分割中，第一部分就是idents
  idents <- factor(x = unlist(x = lapply(
    X = colnames(x = counts), #就是cid
    FUN = ExtractField,
    field = names.field,
    delim = names.delim
  )))


  #如果有些idents是NA，则立刻警告
  if (any(is.na(x = idents))) {
    warning(
      "Input parameters result in NA values for initial cell identities. Setting all initial idents to the project name",
      call. = FALSE,
      immediate. = TRUE
    )
  }

  # if there are more than 100 idents, set all idents to ... name
  ident.levels <- length(x = unique(x = idents)) # 独特 idents 总数
  if (ident.levels > 100 || ident.levels == 0 || ident.levels == length(x = idents)) {
    # 如果 idents 总数超过100，或者没有==0，或者每个cid都是一个idents，
    # 则 设置idents 只有一个，就是项目名字
    idents <- rep.int(x = factor(x = project), times = ncol(x = counts))
  }

  # 命名 idents 的名字为cid
  names(x = idents) <- colnames(x = counts)

  #####################
  # 创建 Seurat 对象
  #####################
  object <- new(
    Class = 'Seurat',
    assays = assay.list, #是一个list，里面的每一个元素是一个 Assay类的实例
    meta.data = data.frame(row.names = colnames(x = counts)), #只有一个空df，行名是cid是counts的列名
    active.assay = assay, #活跃assay是 assay.list 中刚添加的那个list的键
    active.ident = idents, #活跃ident为根据counts列名解析来的，_分割后取第一个，如果没有使用项目名字
    project.name = project, #项目名字
    version = packageVersion(pkg = 'SeuratObject') #创建Seurat对象时的SeuratObject包的版本号
  )

  #####################
  # 为 对象的meta.data 新增列
  # 新增 orig.ident 列
  object[['orig.ident']] <- idents
  
  # Calculate nCount and nFeature
  n.calc <- CalcN(object = counts)
  # 如果非空
  if (!is.null(x = n.calc)) {
    # nCount 变为 nCount_RNA， nFeature 变为 nFeature_RNA
    names(x = n.calc) <- paste(names(x = n.calc), assay, sep = '_') #_后缀表示该属性来自于哪个Assay
    object[[names(x = n.calc)]] <- n.calc #添加2类到 meta.data
  }

  # Add metadata
  if (!is.null(x = meta.data)) {
    # 如果传入参数提供 meta.data，也合并到 meata.data 中。
    object <- AddMetaData(object = object, metadata = meta.data)
  }
  return(object)
}



# seurat-object-4.0.4/R/seurat.R:948:AddMetaData.Seurat <- .AddMetaData
# seurat-object-4.0.4/R/zzz.R:65:.AddMetaData <- function(object, metadata, col.name = NULL) {

#' Add Object Metadata
#'
#' Internal \code{\link{AddMetaData}} definition
#'
#' @param object An object
#' @param metadata A vector, list, or data.frame with metadata to add
#' @param col.name A name for meta data if not a named list or data.frame
#'
#' @return object with metadata added
#'
#' @keywords internal
#'
#' @noRd
#'
.AddMetaData <- function(object, metadata, col.name = NULL) {
  # 如果参数3位空，且参数2是原子状态
  if (is.null(x = col.name) && is.atomic(x = metadata)) {
    #也就是metadata参数是一列vector，则必须给它提供一个列名 col.name，否则报错。
    stop("'col.name' must be provided for atomic metadata types (eg. vectors)") 
  }
  
  # 如果metadata是矩阵，则转为df
  if (inherits(x = metadata, what = c('matrix', 'Matrix'))) {
    metadata <- as.data.frame(x = metadata)
  }

  # col.name如果是空的，则取 names(metadata)，如果还空则取 colnames(metadata)
  col.name <- col.name %||% names(x = metadata) %||% colnames(x = metadata)

  # 如果还是空的，则报错
  if (is.null(x = col.name)) {
    stop("No metadata name provided and could not infer it from metadata object")
  }

  #最后干活的就这一行，添加到Seurat对象的meta.data中
  object[[col.name]] <- metadata
  return(object)
}